﻿
using System.Threading.RateLimiting;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Http;
using Microsoft.Extensions.Options;
using Polly;
using Polly.Extensions.Http;
using SageKing.APIGateway.Yarp.Options;
using SageKing.Core.Extensions;
using Yarp.ReverseProxy.Model;

namespace SageKing.APIGateway.Yarp.Features;

public class SageKingAPIGatewayYarpFeature : FeatureBase
{
    public const string ReverseProxyOptionsName = "ReverseProxy";
    public SageKingAPIGatewayYarpFeature(IModule module) : base(module)
    {
    }

    /// <summary>
    /// Represents the options for ReverseProxy feature.
    /// </summary>
    public Action<ReverseProxyFeature> ReverseProxyOptions { get; set; } = _ => { };
    public Action<RateLimiterOptions> RateLimiterOptions { get; set; } = _ => { };

    /// <inheritdoc />
    public override void Apply(IConfigurationManager configurationManager, IHostEnvironment hostEnvironment)
    {
        Services.Configure(ReverseProxyOptions);
        Services.Configure(RateLimiterOptions);

        Services.AddRateLimiter(RateLimiterOptions);

        Services.AddAuthentication();
        Services.AddAuthorization(options =>
        {
            options.AddPolicy("customPolicy", policy =>
                policy.RequireAuthenticatedUser());
        });

        //add 重试策略,熔断器策略
        Services.AddHttpClient("PollyfiedClient")
                .CreatePolicy(configurationManager);

        Services.AddReverseProxy()
                .LoadFromConfig(configurationManager.GetSection(ReverseProxyOptionsName))
                ;   
        // Add YARP Direct Forwarding with Service Discovery support
        Services.AddHttpForwarderWithServiceDiscovery();
    } 

    public override void Use(IHost app)
    {
        if (app is WebApplication webApp)
        {
            webApp.UseRateLimiter();

            webApp.UseAuthentication();
            webApp.UseAuthorization();

            webApp.MapReverseProxy();
        }
    }
}
